# -*- coding: utf-8 -*-
"""
心灵树洞 - Flask后端应用
为学生提供匿名倾诉平台的后端服务
"""

# 导入必要的库
from flask import Flask, render_template, request, jsonify, redirect, url_for
from flask_sqlalchemy import SQLAlchemy
from datetime import datetime, timezone, timedelta
import os
import base64
from functools import wraps

# 创建Flask应用实例
app = Flask(__name__)

# 配置数据库 - 使用持久化目录存储SQLite数据库文件
# 在Docker容器中，数据将存储在挂载的持久化目录中
# 在本地开发环境中，使用相对路径
if os.path.exists('/app'):  # Docker环境
    data_dir = '/app/data'
    if not os.path.exists(data_dir):
        os.makedirs(data_dir, exist_ok=True)
    
    # 确保数据目录有正确的权限（在Docker环境中）
    try:
        # 尝试在数据目录中创建一个测试文件来验证权限
        test_file = os.path.join(data_dir, '.permission_test')
        with open(test_file, 'w') as f:
            f.write('test')
        os.remove(test_file)
    except (PermissionError, OSError) as e:
        print(f"警告：数据目录权限问题，尝试修复: {e}")
        # 如果权限有问题，尝试使用临时目录
        import tempfile
        data_dir = tempfile.mkdtemp(prefix='hearthole_')
        print(f"使用临时数据目录: {data_dir}")
    
    app.config['SQLALCHEMY_DATABASE_URI'] = f'sqlite:///{data_dir}/database.db'
else:  # 本地开发环境
    app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///database.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
app.config['SECRET_KEY'] = 'heart_hole_secret_key_2024'

# 初始化数据库
db = SQLAlchemy(app)

# 中国时区 (UTC+8)
CHINA_TZ = timezone(timedelta(hours=8))

def get_china_time():
    """获取中国本地时间"""
    return datetime.now(CHINA_TZ)

# 管理员认证信息（硬编码）
ADMIN_USERNAME = 'teacher'
ADMIN_PASSWORD = 'hearthole2024'

# 数据库模型 - 留言表
class Message(db.Model):
    """
    留言数据模型
    注意：严格按照匿名原则，不存储任何用户身份信息
    """
    __tablename__ = 'messages'
    
    # 主键ID，自增
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    
    # 倾诉内容，文本类型
    content = db.Column(db.Text, nullable=False)
    
    # 问题分类标签
    category = db.Column(db.String(50), nullable=False)
    
    # 提交时间，默认为中国本地时间
    timestamp = db.Column(db.DateTime, default=get_china_time, nullable=False)
    
    def __repr__(self):
        return f'<Message {self.id}: {self.category}>'
    
    def to_dict(self):
        """将模型转换为字典格式，便于JSON序列化"""
        return {
            'id': self.id,
            'content': self.content,
            'category': self.category,
            'timestamp': self.timestamp.strftime('%Y-%m-%d %H:%M:%S')
        }

# HTTP Basic Auth装饰器
def require_auth(f):
    """
    HTTP Basic Auth认证装饰器
    用于保护管理员页面
    """
    @wraps(f)
    def decorated(*args, **kwargs):
        auth = request.authorization
        
        # 检查是否提供了认证信息
        if not auth or not check_auth(auth.username, auth.password):
            # 返回401未授权状态，要求浏览器弹出认证对话框
            return ('Authentication Required', 401, {
                'WWW-Authenticate': 'Basic realm="Admin Login"'
            })
        
        return f(*args, **kwargs)
    return decorated

def check_auth(username, password):
    """
    验证用户名和密码
    """
    return username == ADMIN_USERNAME and password == ADMIN_PASSWORD

# 路由定义

@app.route('/')
def index():
    """
    学生端首页路由
    渲染匿名倾诉页面
    """
    return render_template('index.html')

@app.route('/submit', methods=['POST'])
def submit_message():
    """
    接收学生提交的倾诉内容
    处理POST请求，将数据保存到数据库
    """
    try:
        # 获取JSON数据
        data = request.get_json()
        
        # 数据验证
        if not data or 'content' not in data or 'category' not in data:
            return jsonify({'success': False, 'message': '数据格式错误'}), 400
        
        content = data['content'].strip()
        category = data['category'].strip()
        
        # 内容不能为空
        if not content:
            return jsonify({'success': False, 'message': '倾诉内容不能为空'}), 400
        
        # 分类不能为空
        if not category:
            return jsonify({'success': False, 'message': '请选择问题分类'}), 400
        
        # 创建新的留言记录
        new_message = Message(
            content=content,
            category=category
        )
        
        # 保存到数据库
        db.session.add(new_message)
        db.session.commit()
        
        return jsonify({
            'success': True, 
            'message': '你的声音我们已收到，愿你心情阳光灿烂！'
        })
        
    except Exception as e:
        # 发生错误时回滚数据库事务
        db.session.rollback()
        return jsonify({'success': False, 'message': '提交失败，请稍后重试'}), 500

@app.route('/admin')
@require_auth
def admin():
    """
    管理员后台页面路由
    需要HTTP Basic Auth认证
    显示所有学生留言，按时间倒序排列
    """
    try:
        # 获取筛选参数
        category_filter = request.args.get('category', '')
        
        # 构建查询
        query = Message.query
        
        # 如果有分类筛选条件
        if category_filter:
            query = query.filter(Message.category == category_filter)
        
        # 按时间倒序排列（最新的在最上面）
        messages = query.order_by(Message.timestamp.desc()).all()
        
        # 获取所有可用的分类标签（用于筛选下拉框）
        categories = db.session.query(Message.category).distinct().all()
        category_list = [cat[0] for cat in categories]
        
        return render_template('admin.html', 
                             messages=messages, 
                             categories=category_list,
                             current_filter=category_filter)
        
    except Exception as e:
        app.logger.error(f'管理页面加载错误: {str(e)}')
        return f'加载管理页面时发生错误: {repr(e)}', 500

@app.route('/admin/delete/<int:message_id>', methods=['POST'])
@require_auth
def delete_message(message_id):
    """
    删除指定ID的留言
    需要管理员认证
    """
    try:
        # 查找要删除的留言
        message = Message.query.get_or_404(message_id)
        
        # 从数据库中删除
        db.session.delete(message)
        db.session.commit()
        
        return jsonify({
            'success': True,
            'message': '留言删除成功'
        })
        
    except Exception as e:
        # 发生错误时回滚数据库事务
        db.session.rollback()
        app.logger.error(f'删除留言错误: {str(e)}')
        return jsonify({
            'success': False,
            'message': '删除失败，请稍后重试'
        }), 500

# 数据库初始化
def init_db():
    """
    初始化数据库表
    """
    with app.app_context():
        db.create_all()
        print("数据库表创建成功！")

# 应用启动
if __name__ == '__main__':
    # 初始化数据库
    init_db()
    
    # 启动Flask开发服务器
    print("心灵树洞应用正在启动...")
    print("学生端访问地址: http://localhost:5000")
    print("管理员后台: http://localhost:5000/admin")
    print(f"管理员账号: {ADMIN_USERNAME}")
    print(f"管理员密码: {ADMIN_PASSWORD}")
    
    app.run(debug=True, host='0.0.0.0', port=5000)